package com.yinsin.jpabatis.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 根据类完整包名获取到类实体，只是适用于有默认公共构造函数的类 调用某个类的方法 获取对象属性值 获取某个类的某个方法的参数类型
 * 转换value值为相应的类型的值
 * 
 * @author yisin
 *
 */
public class BeanUtils {

	private static Logger log = LoggerFactory.getLogger(BeanUtils.class);

	/**
	 * 根据类完整包名获取到类实体，只是适用于有默认公共构造函数的类
	 * 
	 * @param classPath
	 * @return
	 */
	public static <T> T getBean(String classPath) {
		T t = null;
		try {
			Class<T> aClass = (Class<T>) Class.forName(classPath);
			t = aClass.newInstance();
		} catch (Exception e) {
			t = null;
		}
		return t;
	}

	/**
	 * 调用某个类的方法
	 * 
	 * @param t
	 *            类对象
	 * @param methodName
	 *            方法名
	 * @param param
	 *            参数
	 * @return 结果
	 */
	public static <T> Object callBeanMethod(T t, String methodName, Object[] param) {
		Object result = null;
		try {
			Method method = t.getClass().getMethod(methodName, getParamType(t, methodName));
			result = method.invoke(t, param);
		} catch (NoSuchMethodException e) {
			log.error("NoSuchMethodException：" + t.getClass().getName() + "#" + methodName);
		} catch (SecurityException e) {
			log.error("SecurityException：" + e.getMessage());
		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException：" + t.getClass().getName());
		} catch (IllegalAccessException e) {
			log.error("IllegalAccessException：" + e.getMessage());
		} catch (IllegalArgumentException e) {
			log.error("IllegalArgumentException：" + e.getMessage());
		} catch (InvocationTargetException e) {
			log.error("InvocationTargetException：" + e.getMessage());
		}
		return result;
	}

	/**
	 * 获取对象属性值
	 * 
	 * @param t
	 *            类对象
	 * @param attrName
	 *            属性名
	 * @return 属性值
	 */
	public static <T> Object getFieldValue(T t, String attrName) {
		Object result = null;
		String methodName = Constants.GET + CommonUtils.firstCharToUpperCase(attrName);
		try {
			Method method = t.getClass().getMethod(methodName, new Class<?>[]{});
			result = method.invoke(t, new Object[] {});
		} catch (NoSuchMethodException e) {
			log.error("NoSuchMethodException：" + methodName);
		} catch (SecurityException e) {
			log.error("SecurityException：" + e.getMessage());
		} catch (IllegalAccessException e) {
			log.error("IllegalAccessException：" + e.getMessage());
		} catch (IllegalArgumentException e) {
			log.error("IllegalArgumentException：" + e.getMessage());
		} catch (InvocationTargetException e) {
			log.error("InvocationTargetException：" + e.getMessage());
		}
		return result;
	}
	
	/**
	 * 获取对象属性值
	 * 
	 * @param t
	 *            类对象
	 * @param attrName
	 *            属性名
	 * @return 属性值
	 */
	public static <T> Object getFieldValue(T t, String attrName, Class<?> v) {
		Object result = null;
		String methodName = Constants.GET + CommonUtils.firstCharToUpperCase(attrName);
		try {
			Method method = t.getClass().getMethod(methodName, new Class<?>[]{ v.getClass() });
			result = method.invoke(t, new Object[] {});
		} catch (NoSuchMethodException e) {
			log.error("NoSuchMethodException：" + methodName);
		} catch (SecurityException e) {
			log.error("SecurityException：" + e.getMessage());
		} catch (IllegalAccessException e) {
			log.error("IllegalAccessException：" + e.getMessage());
		} catch (IllegalArgumentException e) {
			log.error("IllegalArgumentException：" + e.getMessage());
		} catch (InvocationTargetException e) {
			log.error("InvocationTargetException：" + e.getMessage());
		}
		return result;
	}

	/**
	 * 获取某个类的某个方法的参数类型
	 * 
	 * @param t
	 *            类对象
	 * @param methodName
	 *            方法
	 * @return 参数类型
	 * @throws ClassNotFoundException
	 */
	public static <T> Class<?>[] getParamType(T t, String methodName) throws ClassNotFoundException {
		Class<?>[] paramTypes = null;
		Method[] methods = t.getClass().getMethods();// 全部方法
		String className = null;
		for (int i = 0; i < methods.length; i++) {
			if (methodName.equals(methods[i].getName())) {// 和传入方法名匹配
				Class<?>[] params = methods[i].getParameterTypes();
				paramTypes = new Class[params.length];
				for (int j = 0; j < params.length; j++) {
					className = params[j].getName();
					if(className.equals("int")){
						paramTypes[j] = Integer.class;
					} else if(className.equals("float")){
						paramTypes[j] = Float.class;
					} else if(className.equals("double")){
						paramTypes[j] = Double.class;
					} else if(className.equals("long")){
						paramTypes[j] = Long.class;
					} else if(className.equals("short")){
						paramTypes[j] = Short.class;
					} else {
						paramTypes[j] = Class.forName(className);
					}
				}
				break;
			}
		}
		return paramTypes;
	}

	/**
	 * 转换value值为相应的类型的值
	 * 
	 * @param value
	 *            值
	 * @param clasz
	 *            值的类型
	 * @return
	 */
	public static Object coventValue(Object value, Class<?> clasz) {
		String type = clasz.getName();
		if (type.equals("java.lang.String")) {
			return value;
		} else if (type.equals("int") || type.equals("java.lang.Integer")) {
			return CommonUtils.objectToInt(value);
		} else if (type.equals("long") || type.equals("java.lang.Long")) {
			return CommonUtils.objectToLong(value);
		} else if (type.equals("float") || type.equals("java.lang.Float")) {
			return CommonUtils.objectToFloat(value, 0.0f);
		} else if (type.equals("double") || type.equals("java.lang.Double")) {
			return CommonUtils.objectToDouble(value, 0.0d);
		} else if (type.equals("java.util.Date")) {
			if (value != null) {
				return new Date();
			}
		} else if (type.equals("java.sql.Timestamp")) {
			if (value != null) {
				return new Timestamp(new Date().getTime());
			}
		} else if (type.equals("java.math.BigDecimal")) {
			if (value != null) {
				return CommonUtils.objectToBigDecimal(value);
			}
		}
		return value;
	}

	/**
	 * 设置对象属性值
	 * 
	 * @param t
	 * @param propertyName
	 * @param value
	 * @return
	 */
	public static <T> Object setProperty(T t, String propertyName, Object value) {
		Object result = null;
		if (t == null) {
			new NullPointerException("类对象为空..");
		}
		result = callBeanMethod(t, "set" + CommonUtils.firstCharToUpperCase(propertyName), new Object[] { value });
		return result;
	}

	/**
	 * 判断类中是否存在某函数
	 * 
	 * @param t
	 *            类对象
	 * @param methodName
	 *            函数名称
	 * @return true:存在，false:不存在
	 */
	public static <T> boolean hasMethod(T t, String methodName) {
		boolean has = false;
		if (t == null) {
			new NullPointerException("类对象为空..");
		}
		try {
			Method method = t.getClass().getMethod(methodName, getParamType(t, methodName));
			if (method != null && method.toString().indexOf("java.lang.Object.toString") == -1) {
				has = true;
			}
		} catch (NoSuchMethodException e) {
			log.error("NoSuchMethodException：" + methodName);
		} catch (SecurityException e) {
			log.error("SecurityException：" + e.getMessage());
		} catch (ClassNotFoundException e) {
			log.error("ClassNotFoundException：" + t.getClass().getName());
		}
		return has;
	}

	/**
	 * 将类对象转换为Map
	 * 
	 * @param t
	 * @return
	 */
	public static <T> Map<String, Object> objectToMap(T t) {
		if (t == null) {
			new NullPointerException("类对象为空..");
		}
		Map<String, Object> map = new HashMap<String, Object>();
		Field[] f = t.getClass().getDeclaredFields();
		if (f != null) {
			String fname, getMethod;
			Object value;
			for (Field field : f) {
				field.getName();
				fname = field.getName();
				getMethod = Constants.GET + CommonUtils.firstCharToUpperCase(fname);
				value = callBeanMethod(t, getMethod, null);
				map.put(fname, value);
			}
		}
		return map;
	}

	/**
	 * 将对象所有属性以及值以字符串形式输出
	 * 
	 * @param t
	 *            类对象
	 * @return
	 */
	public static <T> String toString(T t) {
		String result = t.getClass().toString();
		if (hasMethod(t, "toString")) {
			result = CommonUtils.objectToString(callBeanMethod(t, "toString", null));
		} else {
			Map<String, Object> objMap = objectToMap(t);
			StringBuilder sb = new StringBuilder();
			sb.append(t.getClass().getName()).append("[");
			for (Map.Entry<String, Object> ent : objMap.entrySet()) {
				sb.append(ent.getKey()).append("=").append(ent.getValue()).append(", ");
			}
			sb.append("]");
			result = sb.toString().replaceFirst(", \\]$", "]");
		}
		return result;
	}

	public static String getJavaType(String jdbcType) {
		String javaType = Constants.OBJECT;
		if (jdbcType.equalsIgnoreCase("varchar") || jdbcType.equalsIgnoreCase("char")) {
			javaType = Constants.STRING;
		} else if (jdbcType.equalsIgnoreCase("int") || jdbcType.equalsIgnoreCase("integer")) {
			javaType = Constants.INTEGER;
		} else if (jdbcType.equalsIgnoreCase("long") || jdbcType.equalsIgnoreCase("bigint")) {
			javaType = Constants.LONG;
		} else if (jdbcType.equalsIgnoreCase("float") || jdbcType.equalsIgnoreCase("number")) {
			javaType = Constants.FLOAT;
		} else if (jdbcType.equalsIgnoreCase("double") || jdbcType.equalsIgnoreCase("decimal")) {
			javaType = Constants.DOUBLE;
		} else if (jdbcType.equalsIgnoreCase("date")) {
			javaType = Constants.DATE;
		} else if (jdbcType.equalsIgnoreCase("timestamp") || jdbcType.equalsIgnoreCase("time")) {
			javaType = Constants.TIMESTAMP;
		} else if (jdbcType.equalsIgnoreCase("blob")) {
			javaType = Constants.LBYTE;
		}
		return javaType;
	}

	/**
	 * 对象复制，把 对象2 的属性复制给 对象1
	 * @param o1 对象1
	 * @param o2 对象2
	 * @throws Exception
	 */
	public static <T> T copy(T o1, T o2) throws Exception {
		Field[] field = o1.getClass().getDeclaredFields();
		for (int j = 0; j < field.length; j++) {
			String name = field[j].getName();
			if(hasMethod(o2, "get" + CommonUtils.firstCharToUpperCase(name))){
				Object value2 = getFieldValue(o2, name);
				if (value2 != null) {
					setProperty(o1, name, value2);
				}
			}
		}
		return o1;
	}
	
	/**
	 * 对象复制，把 对象2 的属性复制给 对象1
	 * @param o1 对象1
	 * @param o2 对象2
	 * @throws Exception
	 */
	public static <T> T copy(T o1, T o2, String[] fields) throws Exception {
		if(fields == null){
			return copy(o1, o2);
		} else {
			Field[] field = o1.getClass().getDeclaredFields();
			Map<String, String> fieldMap = new HashMap<String, String>();
			for(int i = 0, k = fields.length; i < k; i++){
				fieldMap.put(fields[i], fields[i]);
			}
			for (int j = 0; j < field.length; j++) {
				String name = field[j].getName();
				if(fieldMap.containsKey(name)){
					if(hasMethod(o2, "get" + CommonUtils.firstCharToUpperCase(name))){
						Object value2 = getFieldValue(o2, name);
						if (value2 != null) {
							setProperty(o1, name, value2);
						}
					}
				}
			}
		}
		return o1;
	}
	
	/**
	 * 对象复制，把 对象2 的属性复制给 对象1
	 * @param o1 对象1
	 * @param o2 对象2
	 * @throws Exception
	 */
	public static <T> T copyNew(T o1, T o2, String[] fields) throws Exception {
		if(fields == null){
			return copyNew(o1, o2);
		} else {
			T newObj = (T) o1.getClass().newInstance();
			newObj = copy(newObj, o1);
			newObj = copy(newObj, o2, fields);
			return newObj;
		}
	}
	
	/**
	 * 对象复制，把 对象2 的属性复制给 对象1
	 * @param o1 对象1
	 * @param o2 对象2
	 * @throws Exception
	 */
	public static <T> T copyNew(T o1, T o2) throws Exception {
		T newObj = (T) o1.getClass().newInstance();
		newObj = copy(newObj, o1);
		newObj = copy(newObj, o2);
		return newObj;
	}

}
